/*
 * Copyright (C) Francisco Morero Peyrona. All rights reserved.
 *
 * This software is published under the terms of Open Source
 * License version 1.1, a copy of which has been included with this
 * distribution in the License.txt file.
 */

package jdbcmanager.dbtools.agentwise;

import java.io.*;

/**
 * Loads a class from the File System.
 * <p>
 * Note: Got from java.sun.com (minumum changes done).
 * 
 * @author Francisco Morero Peyrona
 */
public class FileClassLoader extends ClassLoader
{
   private String sRootDir;

   public FileClassLoader( String sRootDir )
   {
      if( sRootDir == null)
         throw new IllegalArgumentException( "Null root directory" );
         
      this.sRootDir = sRootDir;
   }

   protected Class loadClass( String sName, boolean bResolve ) throws ClassNotFoundException
   {
      // Since all support classes of loaded class use same class loader
      // must check subclass cache of classes for things like Object

      Class clazz = findLoadedClass( sName );
      
      if( clazz == null )
      {
         try
         {
            clazz = findSystemClass( sName );
         }
         catch( Exception exc )
         {
            jdbcmanager.app.App.showDebugException( exc );
         }
      }

      if( clazz == null )
      {
         // Convert class name argument to filename
         // Convert package names into subdirectories
         String filename = sName.replace( '.', File.separatorChar ) + ".class";

         try
         {
            byte data[] = loadClassData(filename);
            clazz = defineClass(sName, data, 0, data.length);
            if (clazz == null)
               throw new ClassNotFoundException(sName);
         }
         catch( IOException exc )
         {
            throw new ClassNotFoundException( "Error reading file: " + filename );
         }
      }
      
      if( bResolve )
         resolveClass( clazz );
      
      return clazz;
   }
   
   
   private byte[] loadClassData(String filename) throws IOException
   {
      // Create a file object relative to directory provided
      File f = new File(sRootDir, filename);

      // Get size of class file
      int size = (int) f.length();

      // Reserve space to read
      byte buff[] = new byte[size];

      // Get stream to read from
      FileInputStream fis = new FileInputStream(f);
      DataInputStream dis = new DataInputStream(fis);

      // Read in data
      dis.readFully(buff);

      // close stream
      dis.close();

      // return data
      return buff;
   }
}